import java.util.concurrent.*;

// concurrent  并发
public class ThreadDemo20 {
    public static void main(String[] args) {

        // Executors 类创建线程池的几种方式, 返回值是 ExecutorService 对象

        // 创建固定线程数的线程池
        ExecutorService pool1 = Executors.newFixedThreadPool(10);

        // 创建线程数目动态增长的线程池
        ExecutorService pool2 = Executors.newCachedThreadPool();

        // 创建只包含单个线程的线程池
        ExecutorService pool3 = Executors.newSingleThreadExecutor();

        // 设定延时时间后执行命令, 或者定期执行命令, 是进阶版的 Timer (定时器)
        ExecutorService pool4 = Executors.newScheduledThreadPool(10);

        // 工厂设计模式,解决构造方法的缺陷（重载参数不能一样, 构造方法需要参数一样的场景）
        // 不直接 new 对象, 通过使用一些方法(通常是静态方法), 协助我们创建对象
        // ThreadPoolExecutor 是原装的线程池类
        // 上述的工厂方法就是对这个类进行封装


        // 重点掌握 ThreadPoolExecutor 类的构造方法的参数, 尤其是拒绝策略

        // ThreadPoolExecutor 类的构造方法的参数

        // 1. 创建一个新 ThreadPoolExecutor 给定的初始参数。
        // ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue)

        // 2. 创建一个新的 ThreadPoolExecutor 与给定的初始参数和默认拒绝执行处理程序。
        // ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler)

        // 3. 创建一个新的 ThreadPoolExecutor 与给定的初始参数和默认线程工厂。
        // ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory)

        // 4. 创建一个新的 ThreadPoolExecutor 与给定的初始参数和默认线程工厂和拒绝执行处理程序。
        // ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)

        // corePoolSize  核心线程数  (正式员工,不能随便辞退)
        // maximumPoolSize  最大线程数  (正式员工 + 实习员工)(任务比较多时, 会创建一些线程, 任务较少时, 会结束一些线程)
        // keepAliveTime  保持存活时间  (任务较少时, 比较空闲, 临时线程保持多久(实习员工保留多久再辞退))
        // unit  保持存活时间的单位, ms, s
        // workQueue  可以手动传一个阻塞队列进去, 线程池里要管理很多任务, 这些队列也是通过队列来组织的
        // threadFactory  工厂模式, 创建线程辅助的类(不具体介绍)
        // handler  线程池的拒接策略, 如果线程池满了, 继续添加任务, 如何拒绝

        // 拒绝策略
        //
        // 线程池满了, 如何拒绝新添加的任务
        //
        // static class  ThreadPoolExecutor.AbortPolicy
        // 抛出一个 RejectedExecutionException 异常。

        // static class  ThreadPoolExecutor.CallerRunsPolicy
        // 在添加任务的线程中, 自己负责执行这个任务

        // static class  ThreadPoolExecutor.DiscardOldestPolicy
        // 丢弃最旧的未处理任务，队首任务

        // static class  ThreadPoolExecutor.DiscardPolicy
        // 丢弃最新的任务, 直接丢弃被拒绝的任务

        // 线程池主要依赖阻塞队列空了时的阻塞行为
        // 线程池不依赖阻塞队列的阻塞行为, 如果队列满了, 明确的拒绝策略更好

        for (int i = 0; i < 1000; i++) {
            int n = i;
            pool1.submit(() -> {
                System.out.println("hello" + n);
            });
        }

        ExecutorService pool5 = new ThreadPoolExecutor(
                10, // 核心线程数
                100,// 最大线程数
                1000,// 最大存活时间
                TimeUnit.MILLISECONDS,// 单位
                new LinkedBlockingDeque<>(),// 阻塞队列
                new ThreadPoolExecutor.AbortPolicy()// 拒绝策略
        );
    }
}
